<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Obj.defineProperty</title>
   
</head>
<body>
  
</body>
</html>
<script>
    //obj.protertype 对象的定性
    //1.对象定义属性和赋值
    //2.Object.definePropert()语法
    //3.属性特性以及内部属性 属性特性、内部属性
    //4.属性描述符 数据描述符、存取描述符、两者共有的特性
    //5.不变性 对象常量、禁止拓展、密封、冻结
    //6.属性定义和属性赋值  属性定义、属性赋值、作用以及影响

    //对象的定义与赋值
    // let  Person = {}
    // Person.name = 'jack'
    // Person['age'] = 10

    //Object.defineProperty()语法说明
    //object.defineProperty()的作用就是直接在一对象上定义一个新的属性，或者修改一个已经存在的属性
    // Object.defineProperty(obj,prop,desc)
    // obj 需要定义属性的当前对象
    // prop 当前需要定义的属性名
    // desc 属性描述符
    // 一般通过对象的属性赋值的情况下，对象的属性可以修改也可以删除，但是通过Object.defineProterty()定义属性，通过描述符的设置可以进行更精准的控制对象属性
    

    // 属性的特性以及内部属性
    // javascript有三种类型的属性
    // 1.命名数据属性：拥有一个确定的值的属性。常见的
    // 2.命名访问器属性：通过getter和setter进行读取和赋值的属性
    // 3.内部属性：由javaScript引擎内部使用的属性，不能通过javaScript代码直接访问到，不过可以通过一些方法间接的读取和设置。比如，每个对象都有一个内部属性[[prototype]],你不能直接访问这个属性，但是可以通过Obj.getPrototypeOf()方法间接读取到他的值。虽然内部属性通常用一个双吕括号包围的名称来表示，但实际上这并不是他们的名字，他们是一种抽象操作，是不可见的，根本没有上面两种属性的那种字符串类型的属性
    // 属性描述符
    // 通过Object.definePropertye()为对象定义属性，有两种形式，且不能混合使用，分别为数据描述符，存取描述符，下面是两者区别
    // 数据描述符  特有的两个属性（value,writable）
    
    // let person = {}
    // Object.defineProperty(person,'name',{
    //     value:'jack',
    //     // writable:false
    // })
    // person.name = 'lilei'
    // console.log(person)

    // 存取描述符 是由一对getter/setter函数功能来描述的属性
    // get: 一个给属性提供getter的方法，如果没有getter则为undefined.该方法返回值被用作属性值。默认为undefined
    // set:一个给属性提供setter的方法，如果没有setter则为undefined.该方法接收唯一参数，并将该参数的新值分配给该属性。默认为undefined.
    
    // let person = {}
    // let temp = null
    // Object.defineProperty(person,'name',{
    //     get:function(){
    //         return temp
    //     },
    //     set:function(val){
    //         temp = val + '0'
    //     }
    // })
    // person.name = 'jack'
    // console.log(person.name)

    // 数据描述符和存取描述符均有以下描述符
    // 1.configrable描述属性是否配置，以及可否删除
    // 2.enumeable描述属性是否会出现在for in或者Object.keys()的遍历中

    // configrable 代码片段分析
    // 'use strict'
    // let person = {}
    // Object.defineProperty(person,'name',{
    //     value:'jack',
    //     writable:true,
    //     configurable:false
    // })
    // Object.defineProperty(person,'name',{
    //     value:'lilei',
    // })
    // person.name = 'lilei'
    // delete person.name
    // console.log(person)
    // configurable:false 不能删除属性、不能重新定义属性


    // enumerable 代码片段分析
    let person = {}
    Object.defineProperty(person,'name',{
        value:'jack',
        enumerable:false
    })
    person.gender = 'male'
    Object.defineProperty(person,'age',{
        value:12,
        enumerable:true
    })
    console.log(Object.keys(person))
    for(let k in person){
        console.log(k)
    }


//     不变性
// 对象常量
// 结合writable: false 和 configurable: false 就可以创建一个真正的常量属性（不可修改，不可重新定义或者删除）

// 禁止扩展
// 如果你想禁止一个对象添加新属性并且保留已有属性，就可以使用Object.preventExtensions(...)



</script>